use crate::errors::{MyError, MyResult};
use crate::models::{ComponentStagingItems, ComposeAreaItem, PageStagingItem, PageStagingItems};
use crate::utils::common;
use crate::vue_parser::VueParser;
use serde::Deserialize;

#[derive(Deserialize)]
struct ComponentStaging {
    pub import: String,
    pub name: String,
}
#[derive(Deserialize)]
struct EventStaging {
    pub event: String,
    pub code: String,
}

pub struct PageTemplateHelper {}
impl PageTemplateHelper {
    pub fn config_template(
        area_item: &ComposeAreaItem,
        pages: &PageStagingItems,
        components: &ComponentStagingItems,
    ) -> MyResult<()> {
        match (
            pages.find(&area_item.page_key),
            components.find(&area_item.component_key),
        ) {
            (Some(page_item), Some(component_item)) => {
                let template_area_key = &area_item.template_area_key;
                let file_content = common::load_project_file(&page_item.module_path)?;

                match VueParser::get_template(&file_content) {
                    Some(template) => {
                        if let Some(new_content) = template.set_tag_content(
                            template.get_cli_tag(template_area_key).as_ref(),
                            &component_item.build_component(),
                        ) {
                            // 将component信息写入到<template>中
                            println!("更新文件:{}", page_item.module_path);
                            common::write_project_file(&page_item.module_path, &new_content)?;

                            // 生成componentsMinxins.staging中间文件
                            common::append_project_file(
                                &page_item.mixins_components_staging_path,
                                &component_item.build_component_staging(),
                            )?;
                            common::append_project_file(
                                &page_item.mixins_methods_staging_path,
                                &component_item.build_events_staging(),
                            )?;
                        }
                        Ok(())
                    }
                    _ => Ok(()),
                }
            }
            _ => Err(MyError::Msg(format!(
                "config_template 失败, template_area_key:{}",
                &area_item.template_area_key
            ))),
        }
    }

    pub fn build_components_mixins(components_mixins_content: &str) -> MyResult<String> {
        let json_content = format!(
            "[{}]",
            &components_mixins_content[..components_mixins_content.len() - 1]
        );
        let items: &Vec<ComponentStaging> = &serde_json::from_str(&json_content)?;

        let import_content = items
            .iter()
            .map(|item| item.import.to_string())
            .collect::<Vec<String>>()
            .join("\n");

        let components_content = items
            .iter()
            .map(|item| item.name.to_string())
            .collect::<Vec<String>>()
            .join(",\n");

        Ok(format!(
            r#"{}

export default {{
    components: {{
    {}
    }}

}}
"#,
            import_content, components_content
        ))
    }
    pub fn build_events_mixins(methods_mixins_content: &str) -> MyResult<String> {
        let json_content = format!(
            "[{}]",
            &methods_mixins_content[..methods_mixins_content.len() - 1]
        );
        let items: &Vec<EventStaging> = &serde_json::from_str(&json_content)?;

        let methods_content = items
            .iter()
            .map(|item| item.code.clone())
            .collect::<Vec<String>>()
            .join(",");

        Ok(format!(
            r#"export default {{
    methods: {{
    {}
    }}
}}
"#,
            methods_content
        ))
    }

    pub fn remove_staging(page_staging_item: &PageStagingItem) -> MyResult<()> {
        common::remove_project_file(&page_staging_item.mixins_components_staging_path)?;
        common::remove_project_file(&page_staging_item.mixins_methods_staging_path)
    }
}
